package com.smarthospital.web.webSocket;

import com.smarthospital.common.util.SpringContextUtil;
import com.smarthospital.service.impl.IMMessageServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;

/**
 * websocket 客户端
 *
 *
 */
@ServerEndpoint("/websocket/{userId}")
@Component
@Slf4j
public class WebSocketServer {

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private static ConcurrentHashMap<String,Session> sessionPools = new ConcurrentHashMap<String,Session>();

    /**
     * 一个用户向服务器发起一个socket连接
     * 服务器端要缓存所有session  关闭连接要丢掉session
     * 建立连接向自身发送一条连接成功的消息
     *
     * 发送消息  根据消息体判断向谁发送消息  如果对方不在线(session不存在) 那么消息设置为未读  入库
     *
     * 接收到一条 消息已读状态处理消息  修改其之前的消息状态为已读
     *
     *
     *
     * 需要一个service处理消息
     */
    /**
     * 建立连接  通过sessionId判断是不是已经纯在的聊天  单体应用 就放在服务器里
     * @param session  session 的 senderId 属性 == 用户的i
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {

        sessionPools.put(userId,session);
        //是否限制聊天室人数

        IMMessageServiceImpl messageService = SpringContextUtil.getBean(IMMessageServiceImpl.class);
        messageService.onOpen(session);
        log.info("有新窗口开始监听:"+userId+",当前在线人数为" + sessionPools.size());
    }

    /*
     * 连接关闭调用的方法
     * 医生端才可以发起关闭，发送一条系统信息给用户端  同时发起关闭订单接口
     */
    @OnClose
    public void onClose(@PathParam("userId") String userId) {
        sessionPools.remove(userId);  //从map中删除
        log.info("有一连接关闭！ userId {} 当前在线人数为 {}" ,userId, sessionPools.size());
    }

    /**
     * 收到客户端消息后调用的方法
     * 存在ES中
     * 发送给对方
     *
     * @param message 客户端发送过来的消息
     **/
    @OnMessage
    public void onMessage(@PathParam("userId") String userId,String message, Session session) {
        log.info("收到来自窗口"+userId+"的信息:"+message);
        IMMessageServiceImpl messageService = SpringContextUtil.getBean(IMMessageServiceImpl.class);
        messageService.onMessage(sessionPools,message);
    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误 error {}", error.getMessage(),error);
    }

}